<?php
/*
	Copyright (C) 2008 - 2012 Inanta Martsanto
	Inanta Martsanto (inanta@inationsoft.com)

	This file is part of NewStep Framework.

	NewStep Framework is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	NewStep Framework is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with NewStep Framework.  If not, see <http://www.gnu.org/licenses/>.
*/

namespace Inationsoft\NS\Database\Driver;

use Inationsoft\NS\Database\Database;
use Inationsoft\NS\Database\IDatabaseDriver;
use Inationsoft\NS\Exception\LibraryException;
use Inationsoft\NS\Exception\DatabaseException;

/**
 *Driver for connecting and handle request to Postgre database sever
 *
 *@author Inanta Martsanto <inanta@inationsoft.com>
 */
class PostgreSQLDriver extends DatabaseDriver implements IDatabaseDriver {
	private $_serverVersion = array();

	function affectedRows() {
		return @pg_affected_rows($this->Result);
	}

	function close() {
		if(!$this->Persistent) @pg_close($this->Connection);
	}

	function connect() {
		$connectionString = "host='".$this->Host."' " .
		    "port='".$this->Port."' " .
		    "dbname='".$this->Database."' " .
		    "user='".$this->Username."' " .
		    "password='".$this->Password . "'" .
		    ($this->Timeout != null ? " connect_timeout='".$this->Timeout."'" : "") .
		    ($this->Options != null ? " options='".$this->Options."'" : "") .
		    ($this->SSLMode != null ? " sslmode='".$this->SSLMode."'" : "");

		$this->Connection = ($this->Persistent ? @pg_pconnect($connectionString) : @pg_connect($connectionString));

		if(@pg_connection_status($this->Connection) !== PGSQL_CONNECTION_OK) throw new DatabaseException(array('code' => UNABLE_TO_CONNECT, 'host' => $this->Host));
		$version = @pg_version($this->Connection);
		$this->_serverVersion = explode('.', $version['server']);
	}
	
	function fetchArray($result = null) {
		$this->assignResult($result);
		return @pg_fetch_array($this->Result, null, PGSQL_BOTH);
	}

	function fetchAssoc($result = null) {
		$this->assignResult($result);
		return @pg_fetch_assoc($this->Result);
	}

	function fetchRow($result = null) {
		$this->assignResult($result);
		return @pg_fetch_row($this->Result);
	}

	function numRows($result  = null) {
		$this->assignResult($result);
		return @pg_num_rows($this->Result);
	}

	function query($query) {
		$this->Result = @pg_query($this->Connection, $query);
		return $this->Result;
	}

	function lastInsertID() {
		if($this->_serverVersion[0] < 8 || ($this->_serverVersion >= 8 && $this->_serverVersion[1] < 1)) throw new UnsupportedOperationException(__FUNCTION__);

		$lastID = $this->query("SELECT LASTVAL()");
		if($row = $this->fetchArray($lastID)) return $row[0];
	}

	static function getInstance($args = array()) { return self::createInstance(__CLASS__, $args); }

	function __construct($args = array()) {
		if(!function_exists('pg_connect')) throw new LibraryException(array('code' => NS_EX_LIB_NOT_INSTALLED, 'class' => __CLASS__, 'library' => 'PostgreSQL'));

		$this->createProperties(array(
						'Host' => isset($args['host']) ? $args['host'] : 'localhost',
						'Port' => isset($args['port']) ? $args['port'] : 5432,
						'Timeout' => isset($args['timeout']) ? $args['timeout'] : null,
						'Options' => isset($args['options']) ? $args['options'] : null,
						'SSLMode' => isset($args['sslmode']) ? $args['sslmode'] : null,
						'Username' => isset($args['username']) ? $args['username'] : KOMA_DB_USER,
						'Password' => isset($args['password']) ? $args['password'] : KOMA_DB_PASS,
						'Database' => isset($args['database']) ? $args['database'] : KOMA_DB_NAME,
						'Persistent' => isset($args['persistent']) ? $args['persistent'] : KOMA_DB_PCONNECTION));

		$this->setReadOnlyProperties(array('Username', 'Password'));
		parent::__construct();
	}

	function __destruct() { $this->close(); }
}
?>
